// 版权归 瞄你个汪 所有。使用本代码应遵守相关法律法规和Apache 2.0开源许可要求。
package top.geeke.toolkit.adminArea;

import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import org.apache.logging.log4j.util.Strings;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.util.*;
import java.util.concurrent.*;

/**
 * <p>
 * 行政地区工具类
 * </p>
 * @author 瞄你个汪
 * @since 2024/5/26 16:32
 */
public class AdminAreaTool {
    private static final String PAGE_URL = "http://xzqh.mca.gov.cn/defaultQuery?shengji=-1&diji=-1&xianji=-1";

    private static AdminAreaItem getRowInfo(Element elem) {
        Elements tds = elem.select("td");

        if (tds == null || tds.isEmpty()) return null;

        String[] array = tds.stream().map(e -> e.text().trim()).toArray(String[]::new);

        AdminAreaItem region = new AdminAreaItem();
        if (Strings.isEmpty(array[0])) return null;
        region.setRegionName(array[0]);

        if (Strings.isNotEmpty(array[1])) region.setStation(array[1]);
        if (Strings.isNotEmpty(array[2])) region.setPopulation(Float.parseFloat(array[2]));
        if (Strings.isNotEmpty(array[3])) region.setArea(Float.parseFloat(array[3]));
        if (Strings.isNotEmpty(array[4])) region.setAreaCode(array[4]);
        if (Strings.isNotEmpty(array[5])) region.setCode(array[5]);
        if (Strings.isNotEmpty(array[6])) region.setZipCode(array[6]);

        return region;
    }

    public static List<AdminAreaItem> getAll() {
        Document doc = Jsoup.parse(HttpUtil.get(PAGE_URL));
        Elements select = doc.select("table.info_table tr");

        List<AdminAreaItem> list = new ArrayList<>();
        select.forEach(a -> {
            AdminAreaItem rowInfo = getRowInfo(a);
            if (rowInfo != null) list.add(rowInfo);
        });

        return list;
    }

    public static List<AdminArea> getProvinceList() {
        String html = HttpUtil.get("http://xzqh.mca.gov.cn/map");

        int index = html.indexOf("var json");

        if (index >= 0 && (index = html.indexOf("[", index)) >= 0) {
            int endIndex = html.indexOf("\n", index);

            if (endIndex < 0) return null;

            return JSONUtil.toList(html.substring(index, endIndex), AdminArea.class);
        }

        return null;
    }

    public static List<AdminArea> getAreaList(AdminArea area) {
        String shengji = area.getShengji();
        String diji = area.getDiji();
        String xianji = area.getXianji();

        String param = "";
        if (Strings.isNotEmpty(shengji)) param += AreaTypeEnum.LEVEL_1.name + "=" + shengji + "&";
        if (Strings.isNotEmpty(diji)) param += AreaTypeEnum.LEVEL_2.name + "=" + diji + "&";
        if (Strings.isNotEmpty(xianji)) param += AreaTypeEnum.LEVEL_3.name + "=" + xianji + "&";

        int index = param.lastIndexOf("&");
        if (index >= 0) param = param.substring(0, index);
        String json = HttpUtil.post("http://xzqh.mca.gov.cn/selectJson", param);
        return JSONUtil.toList(json, AdminArea.class);
    }

    public static List<AdminArea> getAllArea() {
        List<AdminArea> province = getProvinceList();
        if (province == null || province.isEmpty()) return null;

        Queue<List<AdminArea>> queue = new LinkedList<>();
        queue.add(province);

        BlockingQueue<Runnable> runnableList = new LinkedBlockingQueue<>();
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(8, 16, 30, TimeUnit.MINUTES, runnableList);

        while (!queue.isEmpty()) {
            List<AdminArea> tempList = queue.remove();

            System.out.println(Thread.currentThread().getName() + "开始...");
            tempList.forEach(area -> {
                List<AdminArea> children = getAreaList(area);
                if (children != null && !children.isEmpty()) {
                    area.setChildren(children);
                    queue.add(children);
                }
            });
        }


        try {
            threadPool.awaitTermination(5, TimeUnit.MINUTES);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        return province;
    }
}
